#pragma once
#include <memory>
#include <string>
#include <map>

#include "rocksdb/status.h"

namespace rocksdb {
	class ColumnFamilyHandle;
	class DB;

	class DBOptions;
	class ColumnFamilyOptions;
	class Options; 
	class ReadOptions ;
	class WriteOptions;
}


namespace stream {
namespace impl {
namespace rocksdb {

class Table;

class Rocksdb {
public:
    explicit Rocksdb(const std::string & name);
    ~Rocksdb() ;

    static bool exist(const std::string & dbname);
    static bool touch(const std::string & dbname);

    bool isOpened() const;
    bool createIfMissing() ;
    bool openExist() ;

    void close();

	::rocksdb::Status put(const std::string & key, const std::string & value);
	::rocksdb::Status get(const std::string & key, std::string & value);
	::rocksdb::Status del(const std::string & key);
	bool size(size_t & sz) const;
	void clear() ;

	const std::map<std::string, ::rocksdb::ColumnFamilyHandle *> & tables() const;

	std::pair<bool, ::rocksdb::ColumnFamilyHandle*> isTableExist(const std::string & name) const;
	std::shared_ptr<Table> getTable(const std::string & name);
	std::shared_ptr<Table> createTable(const std::string & name);
	bool dropTable(const std::string & name);

protected:
	bool _closeColumnFamilyHandle(::rocksdb::ColumnFamilyHandle * handle);
    bool _openExist();

private:
    std::shared_ptr<::rocksdb::DB> _db;
	std::map<std::string, ::rocksdb::ColumnFamilyHandle*> _tables;
    std::string _name;
    bool _isOpened = false;

	::rocksdb::DBOptions * _dbOptions;
	::rocksdb::ColumnFamilyOptions  * _cfOptions;
	::rocksdb::Options  * _openOptions;
	::rocksdb::ReadOptions  * _readOptions;
	::rocksdb::WriteOptions  * _writeOptions;

	friend class Table;
};

}//end namespace rocksdb
}//end namespace impl
}//end namespace stream
